/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.workflow.service.usertask.impl;

import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.mapper.query.Condition;
import com.je.common.base.mapper.query.ConditionEnum;
import com.je.common.base.service.MetaService;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.ibatis.extension.plugins.pagination.Page;
import com.je.meta.service.QueryBuilderServiceImpl;
import com.je.workflow.service.usertask.CurrentUserParam;
import com.je.workflow.service.usertask.CurrentUserService;
import com.je.workflow.service.usertask.vo.UserTaskVo;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.function.Consumer;

public abstract class AbstractCurrentUserService implements CurrentUserService {
    @Autowired
    protected QueryBuilderServiceImpl queryBuilderService;
    @Autowired
    protected MetaService metaservice;


    public ConditionsWrapper buildConditionsWrapper(CurrentUserParam upcomingParam) {
        ConditionsWrapper conditionsWrapper = ConditionsWrapper.builder();

        if (!Strings.isNullOrEmpty(upcomingParam.getStartTime()) && !Strings.isNullOrEmpty(upcomingParam.getEndTime())) {
            conditionsWrapper.ge("SY_CREATETIME", upcomingParam.getStartTime() + " 00:00:00");
            conditionsWrapper.le("SY_CREATETIME", upcomingParam.getEndTime() + " 59:59:59");
        }

        if (!Strings.isNullOrEmpty(upcomingParam.getUserName())) {
            List<Condition> conditions = new ArrayList<>();
            conditions.add(buildCondition("EXECUTION_STARTER_NAME", upcomingParam.getUserName()));
            conditions.add(buildCondition("EXECUTION_TITLE", upcomingParam.getUserName()));
            conditions.add(buildCondition("ASSIGNEE_NAME", upcomingParam.getUserName()));
            conditions.add(buildCondition("EXECUTION_SUBMIT_USER_NAME", upcomingParam.getUserName()));
            Consumer<ConditionsWrapper> tConsumer = i -> {
                for (Condition c : conditions) {
                    queryBuilderService.condition(i, c, null);
                }
            };
            conditionsWrapper.and(tConsumer);
        }

        if (!Strings.isNullOrEmpty(upcomingParam.getSort())) {
            String[] sortArray = upcomingParam.getSort().split(",");
            List<String> sortIds = Arrays.asList(sortArray);
            conditionsWrapper.in("EXECUTION_PROCESS_KEY", sortIds);
        }
        return conditionsWrapper;
    }

    public Condition buildCondition(String code, String value) {
        Condition condition = new Condition();
        condition.setCn("or");
        condition.setCode(code);
        condition.setValue(value);
        condition.setType(ConditionEnum.LIKE.getType());
        return condition;
    }

    public Map<String, Object> abstractGetRunTask(String tableCode, ConditionsWrapper conditionsWrapper, Page page) {
        conditionsWrapper.orderByDesc("COLLECT_SY_CREATETIME", "SY_CREATETIME");
        List<UserTaskVo> result = new ArrayList<>();
        conditionsWrapper.selectColumns("JE_WORKFLOW_RN_TASK_ID,TASK_DELAY,TABLE_CODE,FUNC_CODE,BUSINESS_KEY,COLLECT_SY_CREATETIME,EXECUTION_PIID,EXECUTION_ASSIGNEE_JSON,EXECUTION_NODE_ID,TASK_HANDLE,EXECUTION_SUBMIT_TYPE,EXECUTION_LAST_COMMENT,EXECUTION_COMMENT,EXECUTION_SUBMIT_USER_NAME,EXECUTION_SUBMIET_USER_ID,TASK_SUBMIT_TYPE_CODE,TASK_SUBMIT_COMMENT,TASK_SUBMIT_USER_NAME,TASK_SUBMIT_USER_ID,SY_CREATEUSERID,EXECUTION_CONTENT,EXECUTION_SUBMIT_TIME,SY_CREATETIME,EXECUTION_COMMIT_TYPE,SY_CREATEUSERNAME,EXECUTION_STARTER,EXECUTION_STARTER_NAME,EXECUTION_TITLE,EXECUTION_START_TIME,FUNC_NAME");
        List<DynaBean> list = metaservice.select(tableCode, page, conditionsWrapper);
        for (DynaBean dynaBean : list) {
            result.add(UserTaskVo.buildRunTask(dynaBean));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("rows", result);
        map.put("totalCount", page.getTotal());
        return map;
    }

    public Map<String, Object> abstractGetEndTask(ConditionsWrapper conditionsWrapper, Page page) {
        List<UserTaskVo> result = new ArrayList<>();
        List<DynaBean> list = metaservice.select("JE_WORKFLOW_V_HI_DONE_TASK", page, conditionsWrapper);
        for (DynaBean dynaBean : list) {
            result.add(UserTaskVo.buildEndTask(dynaBean));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("rows", result);
        map.put("totalCount", page.getTotal());
        return map;
    }

    public long abstractGetRunTaskBadge(String tableCode, ConditionsWrapper conditionsWrapper) {
        String sql = String.format("select count(*) from %s where %s ",
                tableCode, conditionsWrapper.getParameterSql());
        if (sql.toUpperCase().indexOf("GROUP BY") > 0) {
            sql = String.format("select count(*) from (select count(*) from %s  where %s) t",
                    tableCode, conditionsWrapper.getParameterSql());
        }
        List<Map<String, Object>> list = metaservice.selectSql(sql);
        if (list.size() == 1) {
            Map<String, Object> map = list.get(0);
            Set<String> keys = map.keySet();
            Object value = map.get(keys.toArray()[0]);
            return (long) value;
        } else {
            return 0l;
        }
    }

}
